接續上一篇"Day28 - Jetpack DataStore (上) | Preferences DataStore", 今天要介紹的DataStore的另一種實作方式Proto DataStore
。如果還不清楚DataStore的另一種實作方式, 建議可以先回去看上一篇文章。
plugins {
...
id 'com.google.protobuf' version '0.8.12' apply false
}
plugins {
...
id "com.google.protobuf"
}
// Typed DataStore (Typed API surface, such as Proto)
dependencies {
implementation "androidx.datastore:datastore:1.0.0"
implementation "com.google.protobuf:protobuf-javalite:3.14.0"
// 可選 - 支持RxJava2
implementation "androidx.datastore:datastore-rxjava2:1.0.0"
// 可選 - 支持RxJava3
implementation "androidx.datastore:datastore-rxjava3:1.0.0"
}
protobuf {
protoc {
// 這裡設置的版本要和implementation "protobuf-javalite"的版本一致
artifact = "com.google.protobuf:protoc:3.14.0"
}
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option "lite"
}
}
}
}
}
步驟:
注意!!! Proto DataStore要求在app/src/main/proto/
下創建
user_prefs.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.scc.datastorage.proto";
message UserInfo{
String name = 1;
int32 age = 2;
}
建議! 預定義結構的文件以.proto
結尾,這有助於防止不同項目之間的命名衝突。
proto3
語法; 如果沒有這行,protocol-buffers編譯器將假設您使用的是proto2
。注意! 這必是寫在文件的第一個非空、非註釋行才會生效。查看更多!
由於這個範例只是簡單使用Proto DataStore,所以沒有介紹太多protocol-buffres語法,如果想要知道更詳細的,可以到這個網站查看https://developers.google.com/protocol-buffers
完成第一步後一定要做的動作!
預定義結構
那可能表示你環境設置有問題。UserInfo
,所以當重新Rebuild Project
後就會產生出對應的資料類,如下圖所示:定義一個實現Serializer<T>
的類,其中T
是proto文件中定義的類型。
UserInfoSerializer.java
public class UserInfoSerializer implements Serializer<UserInfo> {
@Override
public UserInfo getDefaultValue() {
return UserInfo.getDefaultInstance();
}
@Nullable
@Override
public UserInfo readFrom(@NonNull InputStream inputStream, @NonNull Continuation<? super UserInfo> continuation) {
try {
return UserInfo.parseFrom(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Nullable
@Override
public UserInfo writeTo(UserInfo userInfo, @NonNull OutputStream outputStream, @NonNull Continuation<? super Unit> continuation) {
try {
userInfo.writeTo(outputStream);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
UserInfoDataStore.java
public class UserInfoDataStore {
// 定義DataStore的文件名稱
private final String FILE_NAME = "user_info.pb";
private RxDataStore<UserInfo> dataStore;
public UserInfoDataStore(Context context) {
if (dataStore == null) {
dataStore = new RxDataStoreBuilder<UserInfo>(
context,
/*name=*/ FILE_NAME,
new UserInfoSerializer()).build();
}
}
/**
* 寫入數據 - Name
*/
public void setName(String value) {
dataStore.updateDataAsync(currentUserInfo ->
Single.just(
currentUserInfo.toBuilder()
.setName(value)
.build()
)
);
}
/**
* 寫入數據 - Age
*/
public void setAge(int value) {
dataStore.updateDataAsync(currentUserInfo ->
Single.just(
currentUserInfo.toBuilder()
.setAge(value)
.build()
)
);
}
/**
* 讀取數據 - Name
*/
public String getName() {
return dataStore.data().map(UserInfo::getName).blockingFirst();
}
/**
* 讀取數據 - age
*/
public int getAge() {
return dataStore.data().map(UserInfo::getAge).blockingFirst();
}
}
MainActivity.java
// 獲取DataStore
UserInfoDataStore dataStore = new UserInfoDataStore(this);
//寫入數據
dataStore.setName("Chen");
dataStore.setAge(66);
// 讀取內容
String name = dataStore.getName();
int age = dataStore.getAge();
Log.e("Proto_DataStore_Demo", "讀取到的內容__age:" + age + ", name:" + name);